package com.airlines.base.config.response;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.NoHandlerFoundException;

/**
 * @author luanqing
 * @date 2018年09月10日
 * @description 全局Controller层异常处理
 */
public class GlobalExceptionHandler {
	/**
	 * 记录日志
	 */
	private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);

	/**
	 * 处理所有不可知的异常
	 * @param exception
	 * @return
	 */
	@ExceptionHandler(Exception.class)
	@ResponseBody
	ResponseResult<String> handleException(Exception exception) {
		String trace = getTrace(exception);
		logger.error(trace);
		String errorCode ="500";
		if (exception instanceof NoHandlerFoundException) {
			errorCode = "404";
	    }
		return ResponseResultBuilder.errorResult(null, "请求发生异常", errorCode);
	}

	/**
	 * 处理使用 @Valid 注解验证不通过的处理
	 * 各个controller中的参数后不用再加Bindingesult来处理验证不通过的业务
	 * @param exception
	 * @return
	 */
	@ExceptionHandler(BindException.class)
    public ResponseResult<List<FieldError>> validExceptionHandler(BindException exception) {
        List<FieldError> fieldErrors = exception.getBindingResult().getFieldErrors();
        for (FieldError error:fieldErrors){
            logger.error(error.getField()+":"+error.getDefaultMessage());
        }
        return ResponseResultBuilder.errorResult(fieldErrors, "请求参数验证失败", null);
    }
	
	/**
	 * 处理使用 @Validated 注解验证不通过的处理
	 * 各个controller中的参数后不用再加Bindingesult来处理验证不通过的业务
	 * @param exception
	 * @return
	 */
	@ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseResult<List<FieldError>> validatedExceptionHandler(MethodArgumentNotValidException exception) {
        List<FieldError> fieldErrors = exception.getBindingResult().getFieldErrors();
        for (FieldError error:fieldErrors){
            logger.error(error.getField()+":"+error.getDefaultMessage());
        }
        return ResponseResultBuilder.errorResult(fieldErrors, "请求参数验证失败", null);
    }

	/**
	 * 获取异常栈信息
	 * @param throwable
	 * @return
	 */
	private String getTrace(Throwable throwable) {
		StringWriter stringWriter = new StringWriter();
		PrintWriter writer = new PrintWriter(stringWriter);
		throwable.printStackTrace(writer);
		StringBuffer buffer = stringWriter.getBuffer();
		return buffer.toString();
	}
}
